home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Snippets / OS / SFGetFolder / main.c next >
Encoding:
C/C++ Source or Header  |  1991-10-30  |  7.4 KB  |  338 lines  |  [TEXT/KAHL]

  1. /*    StandardGetFolder example
  2.  
  3.     Steve Falkenburg -- MacDTS
  4.     
  5.     This sample uses the new System 7 CustomGetFile routine
  6.     to provide a StandardGetFolder call to be used by applications
  7.     when the user needs to select a folder instead of a file.
  8.     
  9.     It's written in Think C, but should work in MPW if a few #include
  10.     files are added.
  11.     
  12.     The style of the dialog box is taken from the Human Interface note
  13.     on folder selection.
  14.     
  15.     10/30/91
  16.     
  17. */
  18.  
  19. #include <string.h>
  20. #include <GestaltEqu.h>
  21. #include <Folders.h>
  22. #include <Traps.h>
  23. #include <Script.h>
  24. #include "trapavail.h"
  25.  
  26. /* prototypes */
  27.  
  28. void InitStuff(void);
  29. void CustomGet(void);
  30. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
  31. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
  32. void HitButton(DialogPtr theDlg,short item);
  33. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
  34. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
  35. Boolean SameFile(FSSpec *file1,FSSpec *file2);
  36. Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
  37. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
  38. OSErr MakeCanonFSSpec(FSSpec *fSpec);
  39. Boolean ShouldHiliteSelect(FSSpec *fSpec);
  40.  
  41. /* typedefs */
  42.  
  43. typedef struct {
  44.     StandardFileReply *replyPtr;
  45.     FSSpec oldSelection;
  46. } SFData, *SFDataPtr;
  47.  
  48. /* constants */
  49.  
  50. #define    kSelectItem            10
  51. #define    kSFDlg                128
  52. #define    kCanSelectDesktop    true
  53. #define    kSelectStrRsrc        128
  54. #define kDefaultSelectString "\pSelect"
  55. #define    kDeskStrRsrc        129
  56. #define    kDefaultDeskString    "\pDesktop"
  57. #define    kSelectKey            's'
  58.  
  59. /* globals */
  60.  
  61. Boolean gHasFindFolder;
  62. FSSpec gDeskFolderSpec;
  63. Str255 gSelectString;
  64. Str255 gDesktopFName;
  65.  
  66. void main(void)
  67. {
  68.     InitStuff();
  69.     
  70.     CustomGet();
  71. }
  72.  
  73.  
  74. /* initialize managers */
  75.  
  76. void InitStuff(void)
  77. {
  78.     OSErr err;
  79.     long gResponse;
  80.     Handle strHndl;
  81.     
  82.     MaxApplZone();
  83.     MoreMasters();
  84.     MoreMasters();
  85.     
  86.     InitGraf(&qd.thePort);
  87.     InitFonts();
  88.     InitWindows();
  89.     InitMenus();
  90.     TEInit();
  91.     InitDialogs(nil);
  92.     FlushEvents(everyEvent,0);
  93.     InitCursor();
  94.     
  95.     gHasFindFolder = false;
  96.     if (TrapAvailable(_GestaltDispatch)) {
  97.         err = Gestalt(gestaltFindFolderAttr,&gResponse);
  98.         if (err==noErr)
  99.             gHasFindFolder = (gResponse && (1<<gestaltFindFolderPresent));
  100.     }
  101.     
  102.     strHndl = Get1Resource('STR ',kSelectStrRsrc);
  103.     if (ResError()!=noErr || !strHndl || !*strHndl)
  104.         BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
  105.     else {
  106.         BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
  107.         ReleaseResource(strHndl);
  108.     }
  109.  
  110.     strHndl = Get1Resource('STR ',kDeskStrRsrc);
  111.     if (ResError()!=noErr || !strHndl || !*strHndl)
  112.         BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
  113.     else {
  114.         BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
  115.         ReleaseResource(strHndl);
  116.     }
  117. }
  118.  
  119.  
  120. /* do getfile */
  121.  
  122. void CustomGet(void)
  123. {
  124.     Point where = {-1,-1};
  125.     SFReply reply;
  126.     DialogPtr theDialog;
  127.     short item;
  128.     StandardFileReply sfReply;
  129.     SFData sfUserData;
  130.     
  131.     /* initialize user data area */
  132.     
  133.     sfUserData.replyPtr = &sfReply;
  134.     sfUserData.oldSelection.vRefNum = -9999;    /* init to ridiculous value */
  135.     
  136.     CustomGetFile(FilterAllFiles,-1,nil,&sfReply,kSFDlg,where,MyDlgHook,
  137.                     MyModalFilter,nil,nil,&sfUserData);
  138. }
  139.  
  140.  
  141. /*    this dialog hook checks the contents of the additional edit fields
  142.     when the user selects a file.  The focus of the dialog is changed if one
  143.     of the fields is out of range.
  144. */
  145.  
  146. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
  147. {
  148.     SFDataPtr sfUserData;
  149.     Boolean hiliteButton;
  150.     FSSpec curSpec;
  151.     
  152.     sfUserData = (SFDataPtr) userData;
  153.     
  154.     if (item==sfHookFirstCall || item==sfHookLastCall)
  155.         return item;
  156.     
  157.     if (item==sfItemVolumeUser) {
  158.         sfUserData->replyPtr->sfFile.name[0] = '\0';
  159.         sfUserData->replyPtr->sfFile.parID = 2;
  160.         sfUserData->replyPtr->sfIsFolder = false;
  161.         sfUserData->replyPtr->sfIsVolume = false;
  162.         sfUserData->replyPtr->sfFlags = 0;
  163.         item = sfHookChangeSelection;
  164.     }
  165.         
  166.     if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
  167.         BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
  168.         MakeCanonFSSpec(&curSpec);
  169.         
  170.         if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
  171.             GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);    
  172.         SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
  173.         
  174.         BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
  175.     }
  176.     
  177.     if (item==kSelectItem)
  178.         item = sfItemOpenButton;
  179.         
  180.     return item;
  181. }
  182.  
  183.  
  184. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
  185. {
  186.     Boolean evHandled;
  187.     char keyPressed;
  188.     
  189.     evHandled = false;
  190.     
  191.     switch (ev->what) {
  192.         case keyDown:
  193.         case autoKey:
  194.             keyPressed = ev->message & charCodeMask;
  195.             if ((ev->modifiers & cmdKey) != 0) {
  196.                 switch (keyPressed) {
  197.                     case kSelectKey:
  198.                         HitButton(theDlg,kSelectItem);
  199.                         *itemHit = kSelectItem;
  200.                         evHandled = true;
  201.                         break;
  202.                 }
  203.             }
  204.             break;
  205.     }
  206.     
  207.     return evHandled;
  208. }
  209.  
  210.  
  211. void HitButton(DialogPtr theDlg,short item)
  212. {
  213.     short iType;
  214.     ControlHandle iHndl;
  215.     Rect iRect;
  216.     long fTicks;
  217.     
  218.     GetDItem(theDlg,item,&iType,&iHndl,&iRect);
  219.     HiliteControl(iHndl,inButton);
  220.     Delay(5,&fTicks);
  221.     HiliteControl(iHndl,0);
  222. }
  223.  
  224.  
  225. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
  226. {
  227.     if (pb->hFileInfo.ioFlAttrib & (1<<4))    /* file is a directory */
  228.         return false;
  229.  
  230.     return true;
  231. }
  232.  
  233.  
  234. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
  235. {
  236.     ControlHandle selectButton;
  237.     short iType;
  238.     Handle iHndl;
  239.     Rect iRect;
  240.     Str255 storeName,tempLenStr,tempSelName;
  241.     short btnWidth;
  242.     
  243.     BlockMove(selName,tempSelName,selName[0]+1);
  244.     GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  245.     
  246.     /* truncate select name to fit in button */
  247.     
  248.     btnWidth = iRect.right - iRect.left;
  249.     BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
  250.     p2cstr(tempLenStr);
  251.     strcat((char *)tempLenStr," “”  ");
  252.     c2pstr((char *)tempLenStr);
  253.     btnWidth -= StringWidth(tempLenStr);
  254.     TruncString(btnWidth,tempSelName,smTruncMiddle);
  255.     
  256.     BlockMove(gSelectString,storeName,gSelectString[0]+1);
  257.     p2cstr(storeName);
  258.     p2cstr(tempSelName);
  259.     strcat((char *)storeName," “");
  260.     strcat((char *)storeName,(char *)tempSelName);
  261.     strcat((char *)storeName,"”");
  262.     
  263.     c2pstr((char *)storeName);
  264.     c2pstr(tempSelName);
  265.     SetCTitle(iHndl,storeName);
  266.     
  267.     SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
  268.  
  269.     if (hilited)
  270.         HiliteControl(iHndl,0);
  271.     else
  272.         HiliteControl(iHndl,255);        
  273. }
  274.  
  275.  
  276. Boolean SameFile(FSSpec *file1,FSSpec *file2)
  277. {
  278.     if (file1->vRefNum != file2->vRefNum)
  279.         return false;
  280.     if (file1->parID != file2->parID)
  281.         return false;
  282.     if (!EqualString(file1->name,file2->name,false,true))
  283.         return false;
  284.     
  285.     return true;
  286. }
  287.  
  288.  
  289. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
  290. {
  291.     DirInfo infoPB;
  292.     OSErr err;
  293.     
  294.     if (!gHasFindFolder) {
  295.         fSpec->vRefNum = -9999;
  296.         return -1;
  297.     }
  298.     
  299.     fSpec->name[0] = '\0';
  300.     err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
  301.                         &fSpec->vRefNum,&fSpec->parID);
  302.     if (err!=noErr)
  303.         return err;
  304.     
  305.     return MakeCanonFSSpec(fSpec);
  306. }
  307.  
  308.  
  309. Boolean ShouldHiliteSelect(FSSpec *fSpec)
  310. {
  311.     if (SameFile(fSpec,&gDeskFolderSpec)) {
  312.         BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
  313.         return kCanSelectDesktop;
  314.     }
  315.     else
  316.         return true;
  317. }
  318.  
  319.  
  320. OSErr MakeCanonFSSpec(FSSpec *fSpec)
  321. {
  322.     DirInfo infoPB;
  323.     OSErr err;
  324.  
  325.     if (fSpec->name[0] != '\0')
  326.         return;
  327.         
  328.     infoPB.ioNamePtr = fSpec->name;
  329.     infoPB.ioVRefNum = fSpec->vRefNum;
  330.     infoPB.ioDrDirID = fSpec->parID;
  331.     infoPB.ioFDirIndex = -1;
  332.     err = PBGetCatInfo(&infoPB,false);
  333.     fSpec->parID = infoPB.ioDrParID;
  334.     
  335.     return err;
  336. }
  337.  
  338.